#ifndef __M_HELPER_H__
#define __M_HELPER_H__
#include<iostream>
#include<vector>
#include<random>
#include<sstream>
#include <iomanip>
#include <atomic>
#include<sqlite3.h>
#include<sys/stat.h>
#include<fstream>

#include"logger.hpp"

namespace bitmq{
class Sqlite3Helper{
        public:
        typedef int (*sqliteCallback)(void *, int, char **, char **);
        Sqlite3Helper(const std::string &filename) : _dbfile(filename), _handler(nullptr) {}
        bool open(int safe_level = SQLITE_OPEN_FULLMUTEX){
            int ret = sqlite3_open_v2(_dbfile.c_str(), &_handler, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | safe_level, nullptr);
            if (ret == -1){
                DLOG("打开数据库文件:%s失败",_dbfile);
                return false;
            }
            return true;
        }
        bool exec(const std::string &sql, sqliteCallback cb, void *arg){
            int ret = sqlite3_exec(_handler, sql.c_str(), cb, arg, nullptr);
            if (ret != SQLITE_OK){
                DLOG("执行SQL语句[%s]失败",sql.c_str());
                return false;
            }
            return true;
        }
        void close(){
            if (_handler){
                sqlite3_close_v2(_handler);
            }
        }

    private:
        std::string _dbfile;
        sqlite3 *_handler;  

};
class StrHelper{
    public:
    static size_t stringSpilt(const std::string& str,const std::string& seq,std::vector<std::string>& str_array) {
            if (seq.empty()){
                // 如果分隔符为空，直接将整个字符串作为结果
                str_array.push_back(str);
                return str_array.size();
            }
            int pos = 0, idx = 0;
            while (idx < str.size()){
                pos = str.find(seq, idx);
                if (pos == std::string::npos){
                    str_array.push_back(str.substr(idx));
                    return str_array.size();
                }

                if (pos == idx){
                    idx = pos + seq.size();
                    continue;
                }
                str_array.push_back(str.substr(idx, pos - idx));
                idx = pos + seq.size();
            }
            return str_array.size();
    }
 };
class UUIDHelper{
    public:
       static std::string uuid(){
            std::random_device rd;//rd作为一个随机数引擎，可以随机生成一个机器随机数，但它的效率很低，如果生成太多，整体效率会下降很多
            std::mt19937_64   gernator(rd());//使用一个mt19937_64对象来高效生成随机数，使用rd()产生的数作为随机种子，生成一个随机序列
            std::uniform_int_distribution<int> distribution(0,255);
            std::stringstream str_river;
            for(int i;i<8;i++){
                str_river<<std::setw(2)<<std::setfill('0')<<std::hex<<distribution(gernator);
                if(i==3||i==5||i==7)
                {
                    str_river<<"-";
                }
            } 
            static std::atomic<size_t> seq(1);
            size_t un_num=seq.fetch_add(1);
            for(int i=7;i>=0;i--){
                str_river<<std::setw(2)<<std::setfill('0')<<std::hex<<((un_num>>(i*8)) & 0xff);
                if(i==6){
                    str_river<<"-";
                }
            }
            return str_river.str();
       }
};
class FileHelper{
    public:
        FileHelper(const std::string& filename):_filename(filename){}
        //文件是否存在
        bool exists(){
            struct stat st;
            return ( stat(_filename.c_str(),&st) == 0 );
        }
        static bool exists(const std::string& filename){
            struct stat st;
            return ( stat(filename.c_str(),&st) == 0 );
        }
        //求文件大小
        size_t size(){
            struct stat st;
            if( stat(_filename.c_str(),&st) != 0 ){
                return 0;
            }
            return st.st_size;
        }
        static  size_t size(std::string& filename){
            struct stat st;
            if( stat(filename.c_str(),&st) != 0 ){
                return 0;
            }
            return st.st_size;
        }
        //指定位置读取指定长度文件
        bool read(char* body,size_t offset,size_t len){
            //以二进制模式打开文件
            std::ifstream ifs(_filename,std::ios::binary | std::ios::in);
            if(ifs.is_open() == false){
                DLOG("读取文件时，打开文件[%s]失败",_filename.c_str());
                return false;
            }
            //跳转到预读取位置
            ifs.seekg(offset,std::ios::beg);
            //开始读取数据
            ifs.read(body,len);
            if(ifs.good() == false){
                DLOG("读取文件[%s]不正常",_filename.c_str());
                return false;
            }
            //关闭文件
            ifs.close();
            return true;
        }
        //无脑从头读
        bool read(std::string& body){
            size_t fsize=this->size();
            body.resize(fsize);
            return read(&body[0],0,fsize);
        }
        //在文件指定位置写入指定长度数据
        bool write(const char* body,size_t offset,size_t len){
            //以写方式打开文件
            std::fstream fa(_filename,std::ios::binary | std::ios::in | std::ios::out);
            bool ret=exists(_filename);
            if (fa.is_open() == false) {
                ELOG("%s 文件打开失败！", _filename.c_str());
                return false;
            }
            //让文件调转到指定位置
            fa.seekg(offset,std::ios::beg);
            //写入数据
            fa.write(body,len);
            if(fa.good() == false){
                DLOG("写入文件失败");
                return false;
            }
            fa.close();
            return true;
        }
        //无脑从头写
        bool write(std::string& body)
        {
            size_t len=body.size();
            return write(&body[0],0,len);
        }
        //重命名文件
        bool rename(const std::string &filename){
            return (::rename(_filename.c_str(),filename.c_str()) == 0 );
        }
        //删除文件
        static bool removeFile(const std::string &filename){
            // DLOG("正在删除文件[%s]",filename.c_str());
            return (remove(filename.c_str()) == 0);
        }
        //找到父目录
        static std::string parentDirectory(const std::string& filename)
        {
            size_t pos =filename.find_last_of("/");
            if(pos==std::string::npos){
                return "./";
            }
            std::string tmp_str=filename.substr(0,pos-0);
            return tmp_str;
        }
        //创建文件
        static bool createFile(const std::string& filename){
            std::fstream fs(filename,std::ios::binary | std::ios::out);
            if (fs.is_open() == false) {
                DLOG("%s 文件打开失败！", filename.c_str());
            }
            fs.close();
            return true;
        }
        //创建目录
        static bool createDirectory( const std::string &path){
            int pos=0,idx=0;
            while(idx<path.size()){
                pos=path.find("/",idx);
                if(pos == std::string::npos){
                    return (mkdir(path.c_str(),0775) == 0);
                }
                std::string directory_name = path.substr(0,pos-0);
                int ret=mkdir(directory_name.c_str(),0755);
                if(ret != 0 && errno != EEXIST){
                    return false;
                }
                idx=pos+1;
            }
            return true;
        }
        //删除目录
        static bool removeDirectory(const std::string &path){
            std::string cmd="rm -rf "+path;
            return (system(cmd.c_str()) != -1);
        }
    private:
        std::string _filename;
};
}
#endif